/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file has been modified by Huawei to verify type inference by adding verification statements.
*/

// === tests/cases/compiler/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts ===
declare function AssertType(value:any, type:string):void;
// Note that both of the following have an `any` in their return type from where we bottom out the type printout
// for having too many instances of the same symbol nesting.

// Slightly simplified repro from https://github.com/microsoft/TypeScript/issues/30732 so it's easier to read and debug
export type Key<U> = keyof U;
export type Value<K extends Key<U>, U> = U[K];
export const updateIfChanged = <T>(t: T) => {
AssertType(updateIfChanged, "<T>(T) => (<K extends keyof T>(K) => (<K extends keyof Value<K, T>>(K) => (<K extends keyof Value<K, Value<K, T>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, T>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, T>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>>(K) => any & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, T>>>>) => Value<K, Value<K, Value<K, Value<K, T>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, T>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, T>>>) => Value<K, Value<K, Value<K, T>>>) => T; set: (Value<K, Value<K, Value<K, T>>>) => T; }) & { map: ((Value<K, Value<K, T>>) => Value<K, Value<K, T>>) => T; set: (Value<K, Value<K, T>>) => T; }) & { map: ((Value<K, T>) => Value<K, T>) => T; set: (Value<K, T>) => T; }) & { map: ((T) => T) => T; set: (T) => T; }");
AssertType(t, "T");
AssertType(<T>(t: T) => {    const reduce = <U>(u: U, update: (u: U) => T) => {        const set = (newU: U) => Object.is(u, newU) ? t : update(newU);        return Object.assign(            <K extends Key<U>>(key: K) =>                reduce<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => {                    return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }));                }),            { map: (updater: (u: U) => U) => set(updater(u)), set });    };    return reduce<T>(t, (t: T) => t);}, "<T>(T) => (<K extends keyof T>(K) => (<K extends keyof Value<K, T>>(K) => (<K extends keyof Value<K, Value<K, T>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, T>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, T>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>>(K) => any & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, T>>>>) => Value<K, Value<K, Value<K, Value<K, T>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, T>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, T>>>) => Value<K, Value<K, Value<K, T>>>) => T; set: (Value<K, Value<K, Value<K, T>>>) => T; }) & { map: ((Value<K, Value<K, T>>) => Value<K, Value<K, T>>) => T; set: (Value<K, Value<K, T>>) => T; }) & { map: ((Value<K, T>) => Value<K, T>) => T; set: (Value<K, T>) => T; }) & { map: ((T) => T) => T; set: (T) => T; }");

    const reduce = <U>(u: U, update: (u: U) => T) => {
AssertType(reduce, "<U>(U, (U) => T) => (<K extends keyof U>(K) => (<K extends keyof Value<K, U>>(K) => (<K extends keyof Value<K, Value<K, U>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, U>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, U>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>(K) => any & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, U>>>>) => Value<K, Value<K, Value<K, Value<K, U>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, U>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, U>>>) => Value<K, Value<K, Value<K, U>>>) => T; set: (Value<K, Value<K, Value<K, U>>>) => T; }) & { map: ((Value<K, Value<K, U>>) => Value<K, Value<K, U>>) => T; set: (Value<K, Value<K, U>>) => T; }) & { map: ((Value<K, U>) => Value<K, U>) => T; set: (Value<K, U>) => T; }) & { map: ((U) => U) => T; set: (U) => T; }");
AssertType(u, "U");
AssertType(update, "(U) => T");
AssertType(u, "U");
AssertType(<U>(u: U, update: (u: U) => T) => {        const set = (newU: U) => Object.is(u, newU) ? t : update(newU);        return Object.assign(            <K extends Key<U>>(key: K) =>                reduce<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => {                    return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }));                }),            { map: (updater: (u: U) => U) => set(updater(u)), set });    }, "<U>(U, (U) => T) => (<K extends keyof U>(K) => (<K extends keyof Value<K, U>>(K) => (<K extends keyof Value<K, Value<K, U>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, U>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, U>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>(K) => any & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, U>>>>) => Value<K, Value<K, Value<K, Value<K, U>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, U>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, U>>>) => Value<K, Value<K, Value<K, U>>>) => T; set: (Value<K, Value<K, Value<K, U>>>) => T; }) & { map: ((Value<K, Value<K, U>>) => Value<K, Value<K, U>>) => T; set: (Value<K, Value<K, U>>) => T; }) & { map: ((Value<K, U>) => Value<K, U>) => T; set: (Value<K, U>) => T; }) & { map: ((U) => U) => T; set: (U) => T; }");

        const set = (newU: U) => Object.is(u, newU) ? t : update(newU);
AssertType(set, "(U) => T");
AssertType((newU: U) => Object.is(u, newU) ? t : update(newU), "(U) => T");
AssertType(newU, "U");
AssertType(Object.is(u, newU) ? t : update(newU), "T");
AssertType(Object.is(u, newU), "boolean");
AssertType(Object.is, "(any, any) => boolean");
AssertType(u, "U");
AssertType(newU, "U");
AssertType(t, "T");
AssertType(update(newU), "T");
AssertType(update, "(U) => T");
AssertType(newU, "U");

AssertType(Object.assign(            <K extends Key<U>>(key: K) =>                reduce<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => {                    return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }));                }),            { map: (updater: (u: U) => U) => set(updater(u)), set }), "(<K extends keyof U>(K) => (<K extends keyof Value<K, U>>(K) => (<K extends keyof Value<K, Value<K, U>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, U>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, U>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>(K) => any & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, U>>>>) => Value<K, Value<K, Value<K, Value<K, U>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, U>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, U>>>) => Value<K, Value<K, Value<K, U>>>) => T; set: (Value<K, Value<K, Value<K, U>>>) => T; }) & { map: ((Value<K, Value<K, U>>) => Value<K, Value<K, U>>) => T; set: (Value<K, Value<K, U>>) => T; }) & { map: ((Value<K, U>) => Value<K, U>) => T; set: (Value<K, U>) => T; }) & { map: ((U) => U) => T; set: (U) => T; }");
AssertType(Object.assign, "{ <T extends {}, U>(T, U): T & U; <T extends {}, U, V>(T, U, V): T & U & V; <T extends {}, U, V, W>(T, U, V, W): T & U & V & W; (object, ...any[]): any; }");
        return Object.assign(

            <K extends Key<U>>(key: K) =>
AssertType(key, "K");
AssertType(<K extends Key<U>>(key: K) =>                reduce<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => {                    return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }));                }), "<K extends keyof U>(K) => (<K extends keyof Value<K, U>>(K) => (<K extends keyof Value<K, Value<K, U>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, U>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, U>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>(K) => any & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, U>>>>) => Value<K, Value<K, Value<K, Value<K, U>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, U>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, U>>>) => Value<K, Value<K, Value<K, U>>>) => T; set: (Value<K, Value<K, Value<K, U>>>) => T; }) & { map: ((Value<K, Value<K, U>>) => Value<K, Value<K, U>>) => T; set: (Value<K, Value<K, U>>) => T; }) & { map: ((Value<K, U>) => Value<K, U>) => T; set: (Value<K, U>) => T; }");

                reduce<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => {
AssertType(reduce, "<U>(U, (U) => T) => (<K extends keyof U>(K) => (<K extends keyof Value<K, U>>(K) => (<K extends keyof Value<K, Value<K, U>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, U>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, U>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>(K) => any & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, U>>>>) => Value<K, Value<K, Value<K, Value<K, U>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, U>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, U>>>) => Value<K, Value<K, Value<K, U>>>) => T; set: (Value<K, Value<K, Value<K, U>>>) => T; }) & { map: ((Value<K, Value<K, U>>) => Value<K, Value<K, U>>) => T; set: (Value<K, Value<K, U>>) => T; }) & { map: ((Value<K, U>) => Value<K, U>) => T; set: (Value<K, U>) => T; }) & { map: ((U) => U) => T; set: (U) => T; }");
AssertType(u[key as keyof U] as Value<K, U>, "Value<K, U>");
AssertType(u[key as keyof U], "U[keyof U]");
AssertType(u, "U");
AssertType(key as keyof U, "keyof U");
AssertType(key, "K");
AssertType((v: Value<K, U>) => {                    return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }));                }, "(Value<K, U>) => T");
AssertType(v, "Value<K, U>");
AssertType(reduce<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => {                    return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }));                }), "(<K extends keyof Value<K, U>>(K) => (<K extends keyof Value<K, Value<K, U>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, U>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, U>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>>(K) => any & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, U>>>>) => Value<K, Value<K, Value<K, Value<K, U>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, U>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, U>>>) => Value<K, Value<K, Value<K, U>>>) => T; set: (Value<K, Value<K, Value<K, U>>>) => T; }) & { map: ((Value<K, Value<K, U>>) => Value<K, Value<K, U>>) => T; set: (Value<K, Value<K, U>>) => T; }) & { map: ((Value<K, U>) => Value<K, U>) => T; set: (Value<K, U>) => T; }");

AssertType(update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })), "T");
AssertType(update, "(U) => T");
AssertType(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }), "U & { [string]: Value<K, U>; }");
AssertType(Object.assign, "{ <T extends {}, U>(T, U): T & U; <T extends {}, U, V>(T, U, V): T & U & V; <T extends {}, U, V, W>(T, U, V, W): T & U & V & W; (object, ...any[]): any; }");
AssertType(Array.isArray(u) ? [] : {}, "union");
AssertType(Array.isArray(u), "boolean");
AssertType(Array.isArray, "(any) => arg is any[]");
AssertType(u, "U");
AssertType([], "undefined[]");
AssertType({}, "{}");
AssertType(u, "U");
AssertType({ [key]: v }, "{ [string]: Value<K, U>; }");
AssertType([key], "Value<K, U>");
AssertType(key, "K");
AssertType(v, "Value<K, U>");
                    return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }));

                }),
            { map: (updater: (u: U) => U) => set(updater(u)), set });
AssertType({ map: (updater: (u: U) => U) => set(updater(u)), set }, "{ map: ((U) => U) => T; set: (U) => T; }");
AssertType(map, "((U) => U) => T");
AssertType((updater: (u: U) => U) => set(updater(u)), "((U) => U) => T");
AssertType(updater, "(U) => U");
AssertType(u, "U");
AssertType(set(updater(u)), "T");
AssertType(set, "(U) => T");
AssertType(updater(u), "U");
AssertType(updater, "(U) => U");
AssertType(u, "U");
AssertType(set, "(U) => T");

    };
AssertType(reduce<T>(t, (t: T) => t), "(<K extends keyof T>(K) => (<K extends keyof Value<K, T>>(K) => (<K extends keyof Value<K, Value<K, T>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, T>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, T>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>>(K) => any & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, T>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, T>>>>) => Value<K, Value<K, Value<K, Value<K, T>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, T>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, T>>>) => Value<K, Value<K, Value<K, T>>>) => T; set: (Value<K, Value<K, Value<K, T>>>) => T; }) & { map: ((Value<K, Value<K, T>>) => Value<K, Value<K, T>>) => T; set: (Value<K, Value<K, T>>) => T; }) & { map: ((Value<K, T>) => Value<K, T>) => T; set: (Value<K, T>) => T; }) & { map: ((T) => T) => T; set: (T) => T; }");
AssertType(reduce, "<U>(U, (U) => T) => (<K extends keyof U>(K) => (<K extends keyof Value<K, U>>(K) => (<K extends keyof Value<K, Value<K, U>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, U>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, U>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>(K) => (<K extends keyof Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>(K) => any & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, Value<K, U>>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, Value<K, U>>>>) => Value<K, Value<K, Value<K, Value<K, U>>>>) => T; set: (Value<K, Value<K, Value<K, Value<K, U>>>>) => T; }) & { map: ((Value<K, Value<K, Value<K, U>>>) => Value<K, Value<K, Value<K, U>>>) => T; set: (Value<K, Value<K, Value<K, U>>>) => T; }) & { map: ((Value<K, Value<K, U>>) => Value<K, Value<K, U>>) => T; set: (Value<K, Value<K, U>>) => T; }) & { map: ((Value<K, U>) => Value<K, U>) => T; set: (Value<K, U>) => T; }) & { map: ((U) => U) => T; set: (U) => T; }");
AssertType(t, "T");
AssertType((t: T) => t, "(T) => T");
AssertType(t, "T");
AssertType(t, "T");
    return reduce<T>(t, (t: T) => t);

};

// example from https://github.com/microsoft/TypeScript/issues/31605

export const testRecFun = <T extends Object>(parent: T) => {
AssertType(testRecFun, "<T extends Object>(T) => { result: T; deeper: <U extends Object>(U) => { result: T & U; deeper: <U extends Object>(U) => { result: T & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => any; }; }; }; }; }; }; }; }; }; }; }");
AssertType(parent, "T");
AssertType(<T extends Object>(parent: T) => {    return {        result: parent,        deeper: <U extends Object>(child: U) =>            testRecFun<T & U>({ ...parent, ...child })    };}, "<T extends Object>(T) => { result: T; deeper: <U extends Object>(U) => { result: T & U; deeper: <U extends Object>(U) => { result: T & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => any; }; }; }; }; }; }; }; }; }; }; }");

AssertType({        result: parent,        deeper: <U extends Object>(child: U) =>            testRecFun<T & U>({ ...parent, ...child })    }, "{ result: T; deeper: <U extends Object>(U) => { result: T & U; deeper: <U extends Object>(U) => { result: T & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => any; }; }; }; }; }; }; }; }; }; }; }");
    return {

        result: parent,
AssertType(result, "T");
AssertType(parent, "T");

        deeper: <U extends Object>(child: U) =>
AssertType(deeper, "<U extends Object>(U) => { result: T & U; deeper: <U extends Object>(U) => { result: T & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U & U & U; deeper: any; }; }; }; }; }; }; }; }; }; }; }");
AssertType(<U extends Object>(child: U) =>            testRecFun<T & U>({ ...parent, ...child }), "<U extends Object>(U) => { result: T & U; deeper: <U extends Object>(U) => { result: T & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U & U & U; deeper: any; }; }; }; }; }; }; }; }; }; }; }");
AssertType(child, "U");

            testRecFun<T & U>({ ...parent, ...child })
AssertType(testRecFun<T & U>({ ...parent, ...child }), "{ result: T & U; deeper: <U extends Object>(U) => { result: T & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => any; }; }; }; }; }; }; }; }; }; }; }");
AssertType(testRecFun, "<T extends Object>(T) => { result: T; deeper: <U extends Object>(U) => { result: T & U; deeper: <U extends Object>(U) => { result: T & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => any; }; }; }; }; }; }; }; }; }; }; }");
AssertType({ ...parent, ...child }, "T & U");
AssertType(parent, "T");
AssertType(child, "U");

    };
}


let p1 = testRecFun({ one: '1' })
AssertType(p1, "{ result: { one: string; }; deeper: <U extends Object>(U) => { result: { one: string; } & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => any; }; }; }; }; }; }; }; }; }; }; }");
AssertType(testRecFun({ one: '1' }), "{ result: { one: string; }; deeper: <U extends Object>(U) => { result: { one: string; } & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => any; }; }; }; }; }; }; }; }; }; }; }");
AssertType(testRecFun, "<T extends Object>(T) => { result: T; deeper: <U extends Object>(U) => { result: T & U; deeper: <U extends Object>(U) => { result: T & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => any; }; }; }; }; }; }; }; }; }; }; }");
AssertType({ one: '1' }, "{ one: string; }");
AssertType(one, "string");
AssertType('1', "string");

void p1.result.one;
AssertType(void p1.result.one, "undefined");
AssertType(p1.result.one, "string");

let p2 = p1.deeper({ two: '2' })
AssertType(p2, "{ result: { one: string; } & { two: string; }; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => any; }; }; }; }; }; }; }; }; }; }; }");
AssertType(p1.deeper({ two: '2' }), "{ result: { one: string; } & { two: string; }; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => any; }; }; }; }; }; }; }; }; }; }; }");
AssertType(p1.deeper, "<U extends Object>(U) => { result: { one: string; } & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U & U; deeper: any; }; }; }; }; }; }; }; }; }; }; }");
AssertType({ two: '2' }, "{ two: string; }");
AssertType(two, "string");
AssertType('2', "string");

void p2.result.one;
AssertType(void p2.result.one, "undefined");
AssertType(p2.result.one, "string");

void p2.result.two;
AssertType(void p2.result.two, "undefined");
AssertType(p2.result.two, "string");

let p3 = p2.deeper({ three: '3' })
AssertType(p3, "{ result: { one: string; } & { two: string; } & { three: string; }; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => any; }; }; }; }; }; }; }; }; }; }; }");
AssertType(p2.deeper({ three: '3' }), "{ result: { one: string; } & { two: string; } & { three: string; }; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => any; }; }; }; }; }; }; }; }; }; }; }");
AssertType(p2.deeper, "<U extends Object>(U) => { result: { one: string; } & { two: string; } & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U & U; deeper: any; }; }; }; }; }; }; }; }; }; }; }");
AssertType({ three: '3' }, "{ three: string; }");
AssertType(three, "string");
AssertType('3', "string");

void p3.result.one;
AssertType(void p3.result.one, "undefined");
AssertType(p3.result.one, "string");

void p3.result.two;
AssertType(void p3.result.two, "undefined");
AssertType(p3.result.two, "string");

void p3.result.three;
AssertType(void p3.result.three, "undefined");
AssertType(p3.result.three, "string");


